#include <stdio.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct
{
	int c_semid,g_semid;
	int* data;
}Calculate;
typedef union
{
	int val;
	struct semid_ds* buf;
	unsigned short* array;
}my_semun;
int I(void);
void get_v(Calculate*);
void calculate_v(Calculate*);
void P(int semid);
void V(int semid);
void D(int semid);
int main(void)
{
	key_t k = 888;
	int shmid = shmget(k,sizeof(int),IPC_CREAT | 0777);
	if(shmid == -1)
	{
		perror("shmget error");
		return 1;
	}
	// 映射
	Calculate c;
	c.data = shmat(shmid,0,0);
	c.c_semid = I();
	c.g_semid = I();
	int pid = fork();
	if(pid == -1)
	{
		perror("fork error");
		// 解除映射
		shmdt(c.data);
		// 删除共享内存
		shmctl(shmid,IPC_RMID,NULL);
		// 删除信号量集
		D(c.c_semid);
		D(c.g_semid);
		return 1;
	}
	else if(pid > 0)
	{
		get_v(&c);
		wait(NULL);
		// 删除信号量集
		D(c.c_semid);
		D(c.g_semid);
		// 解除映射
		shmdt(c.data);
		// 删除共享内存
		shmctl(shmid,IPC_RMID,NULL);
	}
	else if(pid == 0)
	{
		calculate_v(&c);
		// 解除映射
		shmdt(c.data);
	}
	return 0;
}
void get_v(Calculate* c)
{
	for(int i = 0;i < 100;i++)
	{
		printf("get; i = %d\n",*c->data);
		*c->data = i;
		V(c->c_semid);
		P(c->g_semid);
		printf("print; i = %d\n--------\n\n",*c->data);
	}
}
void calculate_v(Calculate* c)
{
	for(int i = 0;i < 100;i++)
	{
		P(c->c_semid);
		*c->data += 8;
		printf("calculate; i = %d\n",*c->data);
		V(c->g_semid);
	}
}
int I(void)
{
	// 创建信号量集
	int semid = semget(IPC_PRIVATE,1,IPC_CREAT | 0777);
	if(semid != -1)
	{
		
		my_semun val;
		val.val = 0;
		// 初始化信号量集
		semctl(semid,0,SETALL,&val);
	}
	return semid;
}
void P(int semid)
{
	// 使用sembuf结构体进行P操作
	struct sembuf buf[1] = {{0,-1,SEM_UNDO}};
	semop(semid,buf,1);
}
void V(int semid)
{
	// 使用sembuf结构体进行V操作
	struct sembuf buf[1] = {{0,1,SEM_UNDO}};
	semop(semid,buf,1);
}
void D(int semid)
{
	// 删除信号量集
	semctl(semid,0,IPC_RMID,NULL);
}
